home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software of the Month Club 2000 October
/
Software of the Month - Ultimate Collection Shareware 277.iso
/
pc
/
PROGRAMS
/
UTILITY
/
WINLINUX
/
DATA1.CAB
/
programs_-_kernel_source
/
KERNEL
/
KMOD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-17
|
3KB
|
134 lines
/*
kmod, the new module loader (replaces kerneld)
Kirk Petersen
Reorganized not to be a daemon by Adam Richter, with guidance
from Greg Zornetzer.
Modified to avoid chroot and file sharing problems.
Mikael Pettersson
*/
#define __KERNEL_SYSCALLS__
#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
/*
modprobe_path is set via /proc/sys.
*/
char modprobe_path[256] = "/sbin/modprobe";
static inline void
use_init_file_context(void)
{
struct fs_struct * fs;
lock_kernel();
/*
* Don't use the user's root, use init's root instead.
* Note that we can use "init_task" (which is not actually
* the same as the user-level "init" process) because we
* started "init" with a CLONE_FS
*/
exit_fs(current); /* current->fs->count--; */
fs = init_task.fs;
current->fs = fs;
atomic_inc(&fs->count);
unlock_kernel();
}
static int exec_modprobe(void * module_name)
{
static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL };
int i;
use_init_file_context();
/* Prevent parent user process from sending signals to child.
Otherwise, if the modprobe program does not exist, it might
be possible to get a user defined signal handler to execute
as the super user right after the execve fails if you time
the signal just right.
*/
spin_lock_irq(¤t->sigmask_lock);
flush_signals(current);
flush_signal_handlers(current);
spin_unlock_irq(¤t->sigmask_lock);
for (i = 0; i < current->files->max_fds; i++ ) {
if (current->files->fd[i]) close(i);
}
/* Drop the "current user" thing */
free_uid(current);
/* Give kmod all privileges.. */
current->uid = current->euid = current->fsuid = 0;
cap_set_full(current->cap_inheritable);
cap_set_full(current->cap_effective);
/* Allow execve args to be in kernel space. */
set_fs(KERNEL_DS);
/* Go, go, go... */
if (execve(modprobe_path, argv, envp) < 0) {
printk(KERN_ERR
"kmod: failed to exec %s -s -k %s, errno = %d\n",
modprobe_path, (char*) module_name, errno);
return -errno;
}
return 0;
}
/*
request_module: the function that everyone calls when they need
a module.
*/
int request_module(const char * module_name)
{
int pid;
int waitpid_result;
sigset_t tmpsig;
/* Don't allow request_module() before the root fs is mounted! */
if ( ! current->fs->root ) {
printk(KERN_ERR "request_module[%s]: Root fs not mounted\n",
module_name);
return -EPERM;
}
pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
if (pid < 0) {
printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
return pid;
}
/* Block everything but SIGKILL/SIGSTOP */
spin_lock_irq(¤t->sigmask_lock);
tmpsig = current->blocked;
siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
waitpid_result = waitpid(pid, NULL, __WCLONE);
/* Allow signals again.. */
spin_lock_irq(¤t->sigmask_lock);
current->blocked = tmpsig;
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
if (waitpid_result != pid) {
printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
pid, waitpid_result);
}
return 0;
}